package com.framework.base.interceptor;

import java.util.Map;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;

import com.framework.base.constant.WebConstants;
import com.framework.base.dao.IDManager;
import com.framework.base.service.BaseService;
import com.framework.base.util.BeanUtil;
import com.framework.base.util.DateUtil;
import com.framework.base.util.StringUtil;
import com.framework.base.util.Struts2Utils;
import com.framework.base.util.SysConfUtil;
import com.framework.main.sys.user.domain.UserVo;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.framework.main.sys.log.domain.LogVO;

/**
 * @Description:功能描述：
 * 1、过滤sql注入，可以扩展功能。
 * 2、日志功能 * @author：360buyli.com
 * @version 1.0
 * @Date 2011-6-16 上午09:27:38
 */
public class QueryInterceptor extends AbstractInterceptor {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6410054573418312335L;

	@SuppressWarnings("unchecked")
	@Override
	public String intercept(ActionInvocation actionInvocation) throws Exception {
		// 以下这段代码会在action执行前执行 开始
		Map<String, Object> paramters = (Map<String, Object>) actionInvocation
				.getStack().findValue(WebConstants.TQUERY);
		if (paramters != null) {
			for (Map.Entry<String, Object> paramter : paramters.entrySet()) {
				if (paramter.getValue() != null) {
					paramter.setValue(sqlFilter(paramter.getValue()));
				}
			}
		}
		// 以上这段代码会在action执行前执行 结束

		// 以下代码会在action执行后还没返回页面时执行 开始
		actionInvocation.addPreResultListener(new PreResultListener() {
			public void beforeResult(ActionInvocation invocation,
					String resultCode) {
				Map<String, Object> paramters = (Map<String, Object>) invocation
						.getStack().findValue(WebConstants.TQUERY);
				if (paramters != null) {
					for (Map.Entry<String, Object> paramter : paramters
							.entrySet()) {
						if (paramter.getValue() != null) {
							paramter.setValue(reverseSqlFilter(paramter
									.getValue()));
						}
					}
				}
				try {
					doInsertLog(invocation);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		});
		// 以上代码会在action执行后还没返回页面时执行 结束
		return actionInvocation.invoke();
	}

	/**
	 * 
	 * @Description:功能描述 插入日志
	 * @Date 2011-7-11 下午05:32:58
	 */
	private void doInsertLog(ActionInvocation actionInvocation)
			throws Exception {
		String actionUrl = StringUtil.isNullorEmpty(actionInvocation.getProxy()
				.getConfig().getPackageName()) ? "" : "/"
				+ actionInvocation.getProxy().getConfig().getPackageName()
				+ "/" + actionInvocation.getProxy().getConfig().getName()
				+ ".action";// 构造url
							// 由于使用Struts2Utils.getRequest().getRequestURI()得到的不一定标准，所以自行构造
		boolean isexclude = isExcludeUrl(actionUrl);
		if(!isexclude){
			isexclude = isExcludeActionMethod(actionInvocation.getProxy().getConfig().getClassName(),actionInvocation.getProxy().getConfig().getMethodName());
		}
		if (!isexclude) {
			String navigationbar = StringUtil.nullToEmpty(Struts2Utils
					.getParameter(WebConstants.NAVIGATIONBAR));
			UserVo userVO = Struts2Utils.getCurrentUser();
			LogVO logVO = new LogVO();
			BaseService logService = (BaseService) BeanUtil
					.getServiceBeanById("logService");
			logVO.setLogidf(IDManager.generateID());
			logVO
					.setVisitTimef(DateUtil
							.getCurrentDateTime("yyyy-MM-dd hh:mm"));
			logVO.setNavigationBarf(navigationbar);
			logVO.setActionUrlf(actionUrl);
			logVO.setIpAddressf(Struts2Utils.getRequest().getRemoteHost());
			if (userVO != null) {
				logVO.setUserIdf(userVO.getIdf());
				logVO.setUserNamef(userVO.getUserNamef());
				logVO.setTrueNamef(userVO.getTrueNamef());
			} else {
				logVO.setUserIdf("");
				logVO.setUserNamef("非登陆用户");
				logVO.setTrueNamef("非登陆用户");
			}
			logService.doInsert(logVO);
		}
	}
	/**
	 * 
	 * @Description:功能描述：根据struts_*.xml里的class和method过滤。
	 * @author：刘明云
	 * @Date 2011-7-12 下午05:59:43
	 */
	private boolean isExcludeActionMethod(String className, String methodName) {
		String excludeActionMethods = SysConfUtil.getConfValue(WebConstants.EXCLUDEACTIONMETHOD);
		if(!StringUtil.isNullorEmpty(excludeActionMethods)){
			excludeActionMethods = excludeActionMethods.replaceAll(" ", "");//去空格
			String[] excludeActionMethod = excludeActionMethods.split(",");
			for (String actionMethod : excludeActionMethod) {
				if(!StringUtil.isNullorEmpty(actionMethod)){
					actionMethod = actionMethod.startsWith("/")?actionMethod:"/"+actionMethod;
					if(actionMethod.indexOf("?")!=-1){//有方法的
						if(actionMethod.split("[?]")[0].equals(className)&&actionMethod.split("[?]")[1].equals("method="+methodName)){
							return true;
						}
					}else{//没带方法名的
						if(actionMethod.equals(className)){
							return true;
						}
					}
				}
			}
		}
		return false;
	}

	/**
	 * 
	 * @Description:功能描述:是否是不记录日志的url
	 * @author：刘明云
	 * @Date 2011-7-12 下午05:40:23
	 */
	private boolean isExcludeUrl(String actionUrl) {
			String excludeUrlsLog = SysConfUtil
			.getConfValue(WebConstants.EXCLUEURLLOG);
	if (!StringUtil.isNullorEmpty(excludeUrlsLog)) {
		excludeUrlsLog = excludeUrlsLog.replaceAll(" ", "");//去空格
		String[] excludeUrl = excludeUrlsLog.split(",");
		for (String url : excludeUrl) {
			if (actionUrl.equals(url+".action")||actionUrl.equals("/"+url+".action")) {
				return true;
			}else if(url.indexOf("*")!=-1&&actionUrl.indexOf(url.substring(0, url.indexOf("*")))!=-1){
				return true;
			}
		}
	}
		return false;
	}

	/**
	 * 
	 * @Description:功能描述 替换查询条件值的单引号（把单引号换成''）和空格
	 * @author：刘明云
	 * @Date 2011-6-17 上午11:20:07
	 */
	private Object sqlFilter(Object parameterValues) {
		if (parameterValues == null) {
			return null;
		}
		if (parameterValues instanceof String) {
			String parameterValue = (String) parameterValues;
			parameterValues = StringEscapeUtils.escapeSql(parameterValue);// 过滤sql注入，替换
																			// '
		} else if (parameterValues instanceof String[]) {// 主要是为了容错，如果WebConstants.TQUERY这个对象里面有两个相同的属性（也就是页面有两个一样的属性），则执行这段
			String[] parameterValue = (String[]) parameterValues;
			for (int i = 0; i < parameterValue.length; i++) {
				parameterValue[i] = StringEscapeUtils
						.escapeSql(parameterValue[i]);// 过滤sql注入，替换'
			}
		}
		return parameterValues;

	}

	/**
	 * 
	 * @Description:功能描述 把之前替换成''这个字符变回原来的'，不过空格就不处理了。
	 * @author：刘明云
	 * @Date 2011-6-17 上午11:20:07
	 */
	private Object reverseSqlFilter(Object parameterValues) {
		if (parameterValues == null) {
			return null;
		}
		if (parameterValues instanceof String) {
			String parameterValue = (String) parameterValues;
			parameterValues = StringUtils.replace(parameterValue, "''", "'");// 过滤sql注入，替换
			// '和空格
		} else if (parameterValues instanceof String[]) {// 主要是为了容错，如果WebConstants.TQUERY这个对象里面有两个相同的属性（也就是页面有两个一样的属性），则执行这段
			String[] parameterValue = (String[]) parameterValues;
			for (int i = 0; i < parameterValue.length; i++) {
				parameterValue[i] = StringUtils.replace(parameterValue[i],
						"''", "'");// 过滤sql注入，替换'
			}
		}
		return parameterValues;

	}
}
